/*
 * Copyright (C) 2009-2011 Knowings
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version 3
 * as published by the Free Software Foundation.
 *

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */
package com.knowings.tbs;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import com.knowings.tbs.operation.InvalidParameterException;
import com.knowings.tbs.operation.MissingParameterException;
import com.knowings.tbs.operation.UnsupportedLanguageException;
import com.knowings.tbs.permission.PermissionException;
import com.knowings.tbs.persistence.IAnnotation;
import com.knowings.tbs.trace.BrokenRelationsException;
import com.knowings.tbs.trace.ITrace;
import com.knowings.tbs.trace.IncompatibleTemporalDomainsException;
import com.knowings.tbs.transformation.TransformationRuntimeException;

/**
 * Interface describing Trace Repository compliance level 3 features.
 * 
 * @author privarola
 */
public interface ILevel3Features {
  /**
   * Method changing the name of a trace. This method call is not considered as an amendment.
   * @param uid the UID of the trace
   * @param name the new name of the trace
   * @return the old name of the trace.
   * @exception NoSuchObjectException if no trace with this UID exists in the workspace
   * @exception PermissionException if the connected user does not have the right to rename this trace
   */
  public String setTraceName(String uid, String name) throws PermissionException, NoSuchObjectException;

  /**
   * Method changing the owner of a trace. This method call is not considered as an amendment.
   * @param uid the UID of the trace
   * @param owner the new owner of the trace
   * @return the old owner of the trace.
   * @exception NoSuchObjectException if no trace with this UID exists in the workspace
   * @exception PermissionException if the connected user does not have the right change the owner of this trace
   */
  public String setTraceOwner(String uid, String owner) throws PermissionException, NoSuchObjectException;

  /**
   * Method changing the "active" status of a trace. This method call is not considered as an amendment.
   * @param uid the UID of the trace
   * @param state the new "active" status of the trace
   * @return the old status of the trace.
   * @exception NoSuchObjectException if no trace with this UID exists in the workspace
   * @exception PermissionException if the connected user does not have the right change the "active" status of this trace
   */
  public boolean setTraceActive(String uid, boolean state) throws PermissionException, NoSuchObjectException;

  /**
   * Method splitting a trace into two traces.
   * @param uid the UID of the trace
   * @param date the date of the cut. All obsels with a date inferior or equal to this date will be moved to the "before" trace
   * @param propragate tells whether or not this operation should be propagated to the depending traces
   * @return the UID of the trace created for obsels before the given date, or null if the split date is before the first obsel date
   * @throws PermissionException if the connected user does not have the right to split this trace
   * @throws NoSuchObjectException if no trace with this UID exists in the workspace
   * @throws IncompatibleTemporalDomainsException if propagate is true bot not all depending traces temporal domains are compatible
   * @throws BrokenRelationsException If splitting the trace involves loosing relations that are linked to obsels in the two parts of the trace
   */
  public String splitTrace(String uid, long date, boolean propragate) throws PermissionException,
      NoSuchObjectException, IncompatibleTemporalDomainsException, BrokenRelationsException;

  /**
   * Method splitting several traces using the same date as pivot.
   * @param uids an array containing the UIDs of the traces to be split
   * @param date the date of the cut. All obsels with a date inferior or equal to this date will be moved to the "before" trace
   * @param propragate tells whether or not this operation should be propagated to the depending traces
   * @return an array containing the UIDs of the trace created for obsels before the given date for the traces given as input
   * @throws PermissionException if the connected user does not have the right to split this trace
   * @throws NoSuchObjectException if no trace with this UID exists in the workspace
   * @throws IncompatibleTemporalDomainsException if propagate is true but not all depending traces temporal domains are compatible
   * @throws BrokenRelationsException If splitting the trace involves loosing relations that are linked to obsels in the two parts of the trace
   */
  public String[] splitTraces(String[] uids, long date, boolean propragate) throws PermissionException,
      NoSuchObjectException, IncompatibleTemporalDomainsException, BrokenRelationsException;

  /**
   * Method returning a trace obtained by truncating the trace of given UID after the given obsel date (not included).
   * The returned trace is volatile and its UID will not be known by the repository but the obsels and
   * relations UIDs are those of the original trace. The obsels contained in the returned trace will
   * not show relations with obsels outside the returned trace. 
   * This method is particularly useful to get the delta  between two trace requests. It may return an empty trace.
   * If the ITBSKernel.OPTION_CHAINING_TRACES_SUPPORTED option is supported, the returned trace
   * will give an access to the subtrace before the cut date through the Itrace.getPreceding method.
   * @param uid a String object representing the requested trace UID. This shouldn't be null.
   * @param since a date expressed in the trace temporal domain and relative to the same origin
   * @return a volatile ITrace object which UID is not significant
   * @throws NoSuchObjectException if the UID does not match any known trace in the current workspace
   * @throws PermissionException if the connected user does not have read privileges on the matching trace
   */
  public ITrace getSubTraceAfter(String uid, long since) throws PermissionException, NoSuchObjectException;

  /**
   * Method returning a trace obtained by truncating the trace of given UID before the given obsel date (included).
   * The returned trace is volatile and its UID will not be known by the repository but the obsels and
   * relations UIDs are those of the original trace. The obsels contained in the returned trace will
   * not show relations with obsels outside the returned trace. 
   * If the ITBSKernel.OPTION_CHAINING_TRACES_SUPPORTED option is supported, the returned trace
   * will give an access to the subtrace after the cut date through the Itrace.getFollowing method.
   * @param uid a String object representing the requested trace UID. This shouldn't be null.
   * @param since a date expressed in the trace temporal domain and relative to the same origin
   * @return a volatile ITrace object which UID is not significant
   * @throws NoSuchObjectException if the UID does not match any known trace in the current workspace
   * @throws PermissionException if the connected user does not have read privileges on the matching trace
   */
  public ITrace getSubTraceBefore(String uid, long since) throws PermissionException, NoSuchObjectException;

  /**
   * This method emancipates a TransformedTrace identified by its UID. It does nothing if the trace is already primary.
   * @param uid the UID of the Trace to emancipate
   * @throws PermissionException if the connected user does not have the right to emancipate this trace
   * @throws NoSuchObjectException if no trace with this UID exists in the workspace
   */
  public void emancipateTrace(String uid) throws PermissionException, NoSuchObjectException;

  /**
   * Method removing all obsels of a trace before a given date, inclusive, and all associated relations.
   * @param uid the UID of the trace
   * @param date the date of the cut. All obsels with a date inferior or equal to this date will be removed
   * @throws PermissionException if the connected user does not have the right to purge this trace
   * @throws NoSuchObjectException if no trace with this UID exists in the workspace
   * @throws IncompatibleTemporalDomainsException if not all depending traces temporal domains are compatible
   * @throws BrokenRelationsException if purging the trace at this date involves loosing relations that are linked to obsels in the two parts of the trace
   */
  public void purgeTrace(String uid, long date) throws PermissionException, NoSuchObjectException,
      IncompatibleTemporalDomainsException, BrokenRelationsException;

  /**
   * Method removing all obsels of several trace before a given date, inclusive, and all associated relations.
   * @param uids an array containing the UIDs of the traces to be purged
   * @param date the date of the cut. All obsels with a date inferior or equal to this date will be removed
   * @throws PermissionException if the connected user does not have the right to purge any of the traces
   * @throws NoSuchObjectException if a trace UID is not found in the workspace
   * @throws IncompatibleTemporalDomainsException if not all depending traces temporal domains are compatible
   * @throws BrokenRelationsException if purging the trace at this date involves loosing relations that are linked to obsels in the two parts of the trace
   */
  public void purgeTraces(String[] uids, long date) throws PermissionException, NoSuchObjectException,
      IncompatibleTemporalDomainsException, BrokenRelationsException;

  /**
   * Method adding an annotation on some elements of the current workspace
   * @param uids the UIDs of the objects the annotation should be attached to
   * @param name the name of the annotation
   * @param text the annotation content
   * @return the UID of the created annotation
   * @throws PermissionException if the connected user does not have the right to add an annotation on these elements
   * @throws NoSuchObjectException if any of the referenced entities does not exist in the workspace
   */
  public String addAnnotation(String[] uids, String name, String text) throws PermissionException,
      NoSuchObjectException;

  /**
   * Method returning the annotations related to a specific persistent object
   * @param uid the UID of the target
   * @return the annotations related to the given persistent object
   * @throws PermissionException if the connected user does not have the right to read the target or its annotations
   * @throws NoSuchObjectException if the specified UID is not known in this workspace
   */
  public List<IAnnotation> getRelatedAnnotations(String uid) throws PermissionException, NoSuchObjectException;

  /**
   * Method returning an annotation identified by its UID.
   * @param uid the UID of the target annotation
   * @return the annotation having the given UID
   * @throws PermissionException if the the connected user does not have the right to read the requested annotation
   * @throws NoSuchObjectException if no annotation has this UID in this workspace
   */
  public IAnnotation getAnnotation(String uid) throws PermissionException, NoSuchObjectException;

  /**
   * Method deleting an annotation identified by its UID.
   * @param uid the UID of the target
   * @throws PermissionException if the the connected user does not have the right to delete the requested annotation
   * @throws NoSuchObjectException if no annotation has this UID in this workspace
   */
  public void deleteAnnotation(String uid) throws PermissionException, NoSuchObjectException;

  /**
   * Method updating an existing annotation in the current workspace
   * @param uid the UID of the annotation to be modified
   * @param name the new name of the annotation
   * @param text the new annotation content
   * @throws PermissionException if the connected user does not have the right to modify this annotation
   * @throws NoSuchObjectException if no annotation with this UIS exists in the workspace
   */
  public void updateAnnotation(String uid, String name, String text) throws PermissionException, NoSuchObjectException;

  /**
   * Method executing a reflexive transformation to alter an existing trace identified by the trace_uid parameter.
   * @param trace_uid the UIDs of the traces to be taken into account (and merged) as data source for the transformation
   * @param transformation_uid the UID of the stored transformation to be executed
   * @param parameters a map containing parameter names as keys and parameter values as values
   * @throws NoSuchObjectException if the transformation UID is not found or if any of the source trace UID is not found
   * @throws PermissionException if the connected user does not have the right to modify the source trace, 
   * or to execute the transformation
   * @throws UnsupportedLanguageException if the transformation language is not supported
   * @throws MissingParameterException if a transformation mandatory parameter is not given in the parameters map
   * @throws InvalidParameterException if a transformation parameter does not have the expected type
   * @throws TransformationRuntimeException if the transformation fails due to a syntax problem or internal error
   */
  public void executeReflexiveTransformation(String trace_uid, String transformation_uid,
      Map<String, Serializable> parameters) throws NoSuchObjectException, PermissionException,
      UnsupportedLanguageException, MissingParameterException, InvalidParameterException,
      TransformationRuntimeException;

  /**
   * Method executing a transformation to generate a trace from one or several other.
   * The first operation before the transformation execution is to ensure all involved traces are up-to-date 
   * and make a fusion of them. The resulting trace will be stored in the trace repository as a 
   * <code>ITransformedTrace</code> instance with an association on a <code>ITransformationExecution</code> instance 
   * referencing the used <code>ITransformation</code>.
   * If any of the source trace, or the transformation, is modified, the resulting trace will be kept up-to-date every time it is referenced or requested.
   * The way this trace should be updated is left free and it can be done in lazy or eager mode. 
   * Keep in mind that breaking the monotony of any of the components involved in this transformation implies a full re-computation of the resulting trace.
   * @param trace_uids the UIDs of the traces to be taken into account (and merged) as data source for the transformation
   * @param transformation_uid the UID of the stored transformation to be executed
   * @param parameters a map containing parameter names as keys and parameter values as values
   * @return the UID of the resulting <code>ITransformedTrace</code> instance
   * @throws NoSuchObjectException if the transformation UID is not found or if any of the source trace UID is not found
   * @throws PermissionException if the connected user does not have the right to access a source trace, the transformation,
   * or to create a trace in this workspace
   * @throws UnsupportedLanguageException if the transformation language is not supported
   * @throws MissingParameterException if a transformation mandatory parameter is not given in the parameters map
   * @throws InvalidParameterException if a transformation parameter does not have the expected type
   * @throws IncompatibleTemporalDomainsException if a the source traces does not share the same temporal domain
   * @throws TransformationRuntimeException if the transformation fails due to a syntax problem or internal error
   */
  public String executeContinuousTransformation(String[] trace_uids, String transformation_uid,
      Map<String, Serializable> parameters) throws NoSuchObjectException, PermissionException,
      UnsupportedLanguageException, MissingParameterException, InvalidParameterException,
      IncompatibleTemporalDomainsException, TransformationRuntimeException;
}
